import logging
import json
import string
import random

from django.http import HttpResponse, JsonResponse
from django.views import View
from utils.captcha.captcha import captcha
from django_redis import get_redis_connection

from utils.res_code import Code, error_map
from utils.yuntongxun.sms import CCP
from . import constants
from . import forms

from users.models import Users
from utils.json_func import to_json_data

# 导入日志器
logger = logging.getLogger('django')


# 获取前端传入uuid，生成验证码，返回给前端
class ImageCode(View):
    """
    # 1，创建一个视图类
    verification view
    """

    # 2，从前端获取参数uuid并校验
    def get(self, request, image_code_id):
        # 3，生成图形验证码文本和验证图片码
        text, image = captcha.generate_captcha()
        # 4，建立redis连接，并将图片验证码保存到redis。
        con_redis = get_redis_connection(alias='verify_codes')
        img_key = "img_{}".format(image_code_id)
        con_redis.setex(img_key, constants.IMAGE_CODE_REDIS_EXPIRES, text)

        logger.info('Image_code:{}'.format(text))  # 将验证码信息写入到日志

        # 5，把验证码图片返回给前端
        # print(text)
        return HttpResponse(content=image, content_type='images/jpg')


# 用户名校验
class CheckUsernameView(View):
    '''
    check username whether exists
    GET usernames/(?P<username>\w{5,20})/
    '''

    def get(self, request, username):
        count = Users.objects.filter(username=username).count()  ##如果查询值大于0说明用户名存在，如果等于0说明用户名不存在
        data = {
            'username': username,
            'count': count
        }
        return to_json_data(data=data)


# 手机号校验
class CheckMobileView(View):
    """
    Check whether the phone exists.
    GET mobiles/(r'^1[3-9]/d{9}')/

    """

    def get(self, request, mobile):
        count = Users.objects.filter(phone=mobile).count()  ##如果查询值大于0说明用户名存在，如果等于0说明用户名不存在
        data = {
            'phone': mobile,
            'count': count
        }
        return to_json_data(data=data)


# 短信验证码逻辑
class SmsCodesView(View):
    """
    创建一个类视图
    send mobile sms code
    POST /sms_codes/
    """

    def post(self, request):
        # 2.获取前端参数
        json_data = request.body.decode("utf-8")
        if not json_data:
            return to_json_data(errno=Code.PARAMERR, errmsg="参数为空，请请重新输入！")
        dic_data = json.loads(json_data)  # 将json格式数据转换为dic格式数据，传入空值，会出现报错，所以需要上面的判断

        # 3.校验参数
        form = forms.CheckImgCodeForm(data=dic_data)
        if form.is_valid():  # 执行CheckImgCodeForm里面的方法去校验参数
            # 4.发送短信验证码
            mobile = form.cleaned_data.get("phone")
            # 生成短信验证码
            sms_num = "%06d" % random.randint(0, 999999)

            # 或者
            # sms_num = ''.join([random.choice('0123456789') for _ in range(6)])

            # 5.保存短信验证码和发送记录
            con_redis = get_redis_connection(alias='verify_codes')
            # 创建管道
            pl = con_redis.pipeline()

            # 创建60秒内已发送过短信验证码的标记
            sms_flag_fmt = "sms_flag_{}".format(mobile).encode("utf-8")

            # 创建保存短信验证码的标记key
            sms_text_fmt = "sms_{}".format(mobile).encode("utf-8")

            try:
                # 5.保存短信验证码和发送记录
                pl.setex(sms_flag_fmt, constants.SEND_SMS_CODE_INTERVAL, 1)  # 存储发送短信验证码记录，设置间隔时间
                pl.setex(sms_text_fmt, constants.SMS_CODE_REDIS_EXPIRES, sms_num)  # 存储生成的真实验证码
                pl.execute()
            except Exception as e:
                logger.debug("redis 执行出现异常：{}".format(e))
                return to_json_data(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])

            # 真实短信验证码消息
            logger.info("sms code:{}".format(sms_num))

            # 发送短信验证码
            try:
                result = CCP().send_template_sms(mobile,
                                                 [sms_num, constants.SMS_CODE_REDIS_EXPIRES],
                                                 constants.SMS_CODE_TEMP_ID)
            except Exception as e:
                logger.error("发送验证码短信[异常][ mobile: %s, message: %s ]" % (mobile, e))
                return to_json_data(errno=Code.SMSERROR, errmsg=error_map[Code.SMSERROR])
            else:
                if result == 0:
                    logger.info("发送验证码短信[正常][ mobile: %s sms_code: %s]" % (mobile, sms_num))
                    return to_json_data(errno=Code.OK, errmsg="短信验证码发送成功")
                else:
                    logger.warning("发送验证码短信[失败][ mobile: %s ]" % mobile)
                    return to_json_data(errno=Code.SMSFAIL, errmsg=error_map[Code.SMSFAIL])
        else:
            # 6.返回给前端
            return to_json_data(errno=Code.PARAMERR, errmsg=form.errors)
